/**
* <copyright> Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel modified by Olivier Barais. All rights reserved. This program and the
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html </copyright>
*/
package fr.inria.diverse.k3.benchVM.synthesis.generic.common;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import fr.inria.diverse.k3.benchVM.synthesis.generic.common.attribute.AttributeHandler;
import fr.inria.diverse.k3.benchVM.synthesis.generic.common.attribute.IAttributeSetter;
/**
* Utility class to generate and change Ecore models. All methods should be
* accessed in a way, therefore the constructor is not visible.
*/
public final class ModelGeneratorUtil {
/**
* Set of all EClasses that are contained in EPackages that are currently
* registered in the EPackage registry.
*
* @see #getAllEClasses()
*/
private List<EClass> allEClasses;
/**
* Set of all EPackages that are currently registered in the EPackage
* registry and not contained in any other package.
*
* @see #getAllRootEPackages()
*/
private Set<EPackage> rootModelPackages;
/**
* Map that maps EPackages to a set of all their contained EClasses.
*
* @see #getAllEClasses(EPackage)
*/
private Map<EPackage, List<EClass>> packageToModelElementEClasses = new LinkedHashMap<EPackage, List<EClass>>();
/**
* Map that maps EReferences to all possible EClasses that can be contained
* when using them.
*
* @see #getAllEContainments(EReference)
*/
private Map<EReference, List<EClass>> allEContainments = new LinkedHashMap<EReference, List<EClass>>();
/**
* Map that maps EClasses to their subclasses.
*
* @see #getAllSubEClasses(EClass)
*/
private Map<EClass, List<EClass>> eClassToSubEClasses = new LinkedHashMap<EClass, List<EClass>>();
/**
* Returns the EPackage to the specified <code>nsURI</code>.
*
* @param nsURI
* the NsUri of the EPackage to get
* @return the EPackage belonging to <code>nsURI</code>
* @see Registry#getEPackage(String)
*/
public EPackage getEPackage(String nsURI) {
return EPackage.Registry.INSTANCE.getEPackage(nsURI);
}
/**
* Returns all EPackages on the root level that are currently registered in
* the registry.
*
* @return a Set of all root EPackages
* @see Registry
*/
public Set<EPackage> getAllRootEPackages() {
// were the root packages computed before?
if (rootModelPackages != null) {
return rootModelPackages;
}
rootModelPackages = new LinkedHashSet<EPackage>();
Registry registry = EPackage.Registry.INSTANCE;
for (Entry<String, Object> entry : registry.entrySet()) {
EPackage ePackage = registry.getEPackage(entry.getKey());
// is the current EPackage a root package?
if (ePackage.getESuperPackage() == null) {
rootModelPackages.add(ePackage);
}
}
return rootModelPackages;
}
/**
* Retrieve all EClasses that are contained in <code>ePackage</code>.
*
* @param ePackage
* the package to get contained EClasses from
* @return a set of EClasses contained in <code>ePackage</code>
*/
public List<EClass> getAllEClasses(EPackage ePackage) {
if (packageToModelElementEClasses.containsKey(ePackage)) {
return packageToModelElementEClasses.get(ePackage);
}
if (ePackage == null) {
packageToModelElementEClasses.put(ePackage,
new LinkedList<EClass>());
return packageToModelElementEClasses.get(ePackage);
}
List<EClass> result = new LinkedList<EClass>();
// obtain all EClasses from sub packages
for (EPackage subPackage : ePackage.getESubpackages()) {
result.addAll(getAllEClasses(subPackage));
}
// obtain all EClasses that are direct contents of the EPackage
for (EClassifier classifier : ePackage.getEClassifiers()) {
if (classifier instanceof EClass) {
result.add((EClass) classifier);
}
}
// save the result for upcoming method calls
packageToModelElementEClasses.put(ePackage, result);
return result;
}
/**
* Iterates over all registered EPackages in order to retrieve all available
* EClasses, excluding abstract classes and interfaces, and returns them as
* a Set.
*
* @return a set of all EClasses that are contained in registered EPackages
* @see Registry
*/
public List<EClass> getAllEClasses() {
// were all EClasses computed before?
if (allEClasses != null) {
return allEClasses;
}
allEClasses = new LinkedList<EClass>();
Registry registry = EPackage.Registry.INSTANCE;
// for all registered EPackages
for (Entry<String, Object> entry : registry.entrySet()) {
EPackage ePackage = registry.getEPackage(entry.getKey());
for (EClass eClass : getAllEClasses(ePackage)) {
// no abstracts or interfaces
if (canHaveInstance(eClass)) {
allEClasses.add(eClass);
}
}
}
return allEClasses;
}
/**
* Returns all possible EClasses, excluding abstract classes and interfaces,
* that can be contained when using <code>reference</code>.
*
* @param reference
* the EReference to get containable EClasses for
* @return a set of all EClasses that can be contained when using
* <code>reference</code>
*/
public List<EClass> getAllEContainments(EReference reference) {
if (allEContainments.containsKey(reference)) {
return allEContainments.get(reference);
}
if (reference == null) {
allEContainments.put(reference, new LinkedList<EClass>());
return allEContainments.get(reference);
}
List<EClass> result = new LinkedList<EClass>();
EClass referenceType = reference.getEReferenceType();
// no abstracts or interfaces
if (canHaveInstance(referenceType)) {
result.add(referenceType);
}
// 'referenceType: EObject' allows all kinds of EObjects
if (EcorePackage.eINSTANCE.getEObject().equals(referenceType)) {
return getAllEClasses();
}
// all sub EClasses can be referenced as well
result.addAll(getAllSubEClasses(referenceType));
// save the result for upcoming method calls
allEContainments.put(reference, result);
return result;
}
/**
* Returns whether <code>eClass</code> can be instantiated or not. An EClass
* can be instantiated, if it is neither an interface nor abstract.
*
* @param eClass
* the EClass in question
* @return whether <code>eClass</code> can be instantiated or not.
*/
public boolean canHaveInstance(EClass eClass) {
return !eClass.isInterface() && !eClass.isAbstract();
}
/**
* Returns all subclasses of an EClass, excluding abstract classes and
* interfaces.
*
* @param eClass
* the EClass to get subclasses for
* @return all subclasses of <code>eClass</code>
*/
public List<EClass> getAllSubEClasses(EClass eClass) {
if (eClassToSubEClasses.containsKey(eClass)) {
return eClassToSubEClasses.get(eClass);
}
if (eClass == null) {
eClassToSubEClasses.put(eClass, new LinkedList<EClass>());
return eClassToSubEClasses.get(eClass);
}
List<EClass> allEClasses = getAllEClasses();
List<EClass> result = new LinkedList<EClass>();
for (EClass possibleSubClass : allEClasses) {
// is the EClass really a subClass, while not being abstract or an
// interface?
if (eClass.isSuperTypeOf(possibleSubClass)
&& canHaveInstance(possibleSubClass)) {
result.add(possibleSubClass);
}
}
// save the result for upcoming method calls
eClassToSubEClasses.put(eClass, result);
return result;
}
/**
* Returns all containing references where <code>parentClass</code> is the
* container and <code>childClass</code> the containment.
*
* @param childClass
* the EClass which shall be contained
* @param parentClass
* the EClass to get containment references from
* @return all possible container-references as a set
*/
public Set<EReference> getAllPossibleContainingReferences(
EClass childClass, EClass parentClass) {
List<EReference> allReferences = parentClass.getEAllContainments();
Set<EReference> result = new LinkedHashSet<EReference>();
for (EReference reference : allReferences) {
EClass referenceType = reference.getEReferenceType();
if (referenceType == null) {
continue;
}
// is the reference type a perfect match?
if (referenceType.equals(childClass)) {
result.add(reference);
// is the reference type either EObject or a super type?
} else if (referenceType
.equals(EcorePackage.eINSTANCE.getEObject())
|| referenceType.isSuperTypeOf(childClass)) {
result.add(reference);
}
}
return result;
}
/**
* Returns all direct and indirect contents of <code>rootObject</code> as a
* map. All EObjects that appear in these contents are mapped to their
* corresponding EClass.
*
* @param rootObject
* the EObject to get contents for
* @return all contents as a map from EClass to lists of EObjects
*/
public Map<EClass, List<EObject>> getAllClassesAndObjects(
EObject rootObject) {
// initialize the computation process
Map<EClass, List<EObject>> result = new LinkedHashMap<EClass, List<EObject>>();
TreeIterator<EObject> allContents = rootObject.eAllContents();
List<EObject> newList = new LinkedList<EObject>();
newList.add(rootObject);
result.put(rootObject.eClass(), newList);
// iterate over all direct and indirect contents
while (allContents.hasNext()) {
EObject eObject = allContents.next();
// did this EObject's EClass appear before?
if (result.containsKey(eObject.eClass())) {
result.get(eObject.eClass()).add(eObject);
} else {
newList = new LinkedList<EObject>();
newList.add(eObject);
result.put(eObject.eClass(), newList);
}
}
return result;
}
/**
* Returns all valid references for an EObject. This excludes
* container/containment references. A reference is valid if it is neither
* derived nor volatile and if it is changeable and either many-valued or
* not already set.
*
* @param eObject
* the EObject to get references for
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @return all valid references as a list
*/
public List<EReference> getValidReferences(EObject eObject,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
List<EReference> result = new LinkedList<EReference>();
for (EReference reference : eObject.eClass().getEAllReferences()) {
if (!reference.isContainer() && !reference.isContainment()
&& isValid(reference, eObject, exceptionLog, ignoreAndLog)
&& (reference.isMany() || !eObject.eIsSet(reference))) {
if (!reference.getName().equals("eTypeArguments"))
result.add(reference);
} else {
if (reference.getName().toLowerCase().equals("etype")) {
result.add(reference);
//System.err.println(reference.getName());
}
}
}
return result;
}
/**
* Returns whether an EStructuralFeature is valid for an EObject or not. A
* reference is valid, if it can be set or added to.
*
* @param feature
* the EStructuralFeature in question
* @param eObject
* the EObject to check the feature for
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @return if the feature can be set or added to
*/
public boolean isValid(EStructuralFeature feature, EObject eObject,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
boolean result = false;
try {
if (feature.isMany()) {
// has the maximum amount of referenced objects been reached?
Collection<?> referencedItems = (Collection<?>) eObject
.eGet(feature);
if (feature.getUpperBound() >= 0
&& referencedItems.size() >= feature.getUpperBound()) {
return false;
}
}
// can the feature be changed reflectively?
result = feature.isChangeable() /* && !feature.isVolatile() */
&& !feature.isDerived();
if (feature.getName().equals("eType"))
result = true;
if (feature.getName().equals("defaultValueLiteral"))
result = false;
/*
* else if (feature.getName().contains("instance")){
* System.err.println(result + " : "+ feature.getName());
* System.err.println( feature.isChangeable() + " "+
* !feature.isVolatile() + " "+ !feature.isDerived()); }
*/
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
}
return result;
}
/**
* Handles <code>exception</code>, meaning it is thrown if
* <code>ignoreAndLog</code> is <code>false</code>. Otherwise
* <code>exception</code> is ignored and added to <code>exceptionLog</code>.
*
* @param exception
* the exception to handle
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
*/
private void handle(RuntimeException exception,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
if (ignoreAndLog) {
exceptionLog.add(exception);
} else {
throw exception;
}
}
/**
* Sets a feature between <code>eObject</code> and <code>newValue</code>
* using a SetCommand. Exceptions are caught if <code>ignoreAndLog</code> is
* true, otherwise a RuntimeException might be thrown if the command fails.
*
* @param eObject
* the EObject for which <code>feature</code> shall be set
* @param feature
* the EStructuralFeature that shall be set
* @param newValue
* the Object that shall be set as a feature in
* <code>parentEObject</code>
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @return <code>newValue</code> if the <code>SetCommand</code> was
* performed successful or <code>null</code> if it failed
* @see SetCommand
*/
public EObject setPerCommand(EObject eObject,
EStructuralFeature feature, Object newValue,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
EditingDomain domain = AdapterFactoryEditingDomain
.getEditingDomainFor(eObject);
if (domain == null) {
// System.err.println("no editing domain for " + eObject);
// return null;
} else {
// System.err.println("editing domain for " + eObject + " " +
// domain);
}
// no new value to set? -> unset the feature
if (newValue == null) {
newValue = SetCommand.UNSET_VALUE;
}
try {
eObject.eSet(feature, newValue);
// new SetCommand(domain, eObject, feature, newValue).doExecute();
if (newValue instanceof EObject) {
return (EObject) newValue;
} else {
return null;
}
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
return null;
}
}
/**
* Adds <code>newValue</code> to the many-valued feature of
* <code>eObject</code> using an AddCommand. Exceptions are caught if
* <code>ignoreAndLog</code> is true, otherwise a RuntimeException might be
* thrown if the command fails.
*
* @param eObject
* the EObject to which <code>newObject</code> shall be added
* @param feature
* the EStructuralFeature that <code>newObject</code> shall be
* added to
* @param newValue
* the Object that shall be added to <code>feature</code>
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @return <code>newValue</code> if the <code>AddCommand</code> was
* performed successful or <code>null</code> if it failed
* @see AddCommand#AddCommand(EditingDomain, EObject, EStructuralFeature,
* Object)
*/
public EObject addPerCommand(EObject eObject,
EStructuralFeature feature, Object newValue,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
EditingDomain domain = AdapterFactoryEditingDomain
.getEditingDomainFor(eObject);
try {
if (feature.isUnique()
&& ((Collection<?>) eObject.eGet(feature))
.contains(newValue)) {
// unique feature already contains object -> nothing to do
return null;
}
new AddCommand(domain, eObject, feature, newValue).doExecute();
if (newValue instanceof EObject) {
return (EObject) newValue;
} else {
return null;
}
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
return null;
}
}
/**
* Adds all <code>objects</code> to the many-valued feature of
* <code>eObject</code> using an AddCommand. Exceptions are caught if
* <code>ignoreAndLog</code> is true, otherwise a RuntimeException might be
* thrown if the command fails.
*
* @param eObject
* the EObject to which <code>objects</code> shall be added
* @param feature
* the EReference that <code>objects</code> shall be added to
* @param objects
* collection of objects that shall be added to
* <code>feature</code>
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
*/
public void addPerCommand(EObject eObject,
EStructuralFeature feature, Collection<?> objects,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
EditingDomain domain = AdapterFactoryEditingDomain
.getEditingDomainFor(eObject);
try {
for (Object object : objects) {
if (feature.isUnique()
&& ((Collection<?>) eObject.eGet(feature))
.contains(object)) {
// object already exists in unique feature, don't add it
// again
objects.remove(object);
}
}
// no objects to add left
if (objects.isEmpty()) {
return;
}
new AddCommand(domain, eObject, feature, objects).doExecute();
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
}
}
/**
* Removes <code>objects</code> from a feature of <code>eObject</code> using
* a RemoveCommand. Exceptions are caught if <code>ignoreAndLog</code> is
* true, otherwise a RuntimeException might be thrown if the command fails.
*
* @param eObject
* the EObject to remove <code>objects</code> from
* @param feature
* the EStructuralFeature <code>objects</code> shall be removed
* from
* @param objects
* collection of Objects that shall be removed
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @see RemoveCommand
*/
public void removePerCommand(EObject eObject,
EStructuralFeature feature, Collection<?> objects,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
EditingDomain domain = AdapterFactoryEditingDomain
.getEditingDomainFor(eObject);
try {
new RemoveCommand(domain, eObject, feature, objects).doExecute();
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
}
}
/**
* Retrieves all EClasses from <code>allEClasses</code> that can possibly be
* referenced by <code>reference</code> and returns them as a list.
*
* @param reference
* the EReference to get EClasses for
* @param allEClasses
* set of all possible EClasses
* @return list of all EClasses that can be referenced by
* <code>reference</code>
*/
public Set<EClass> getReferenceClasses(EReference reference,
Set<EClass> allEClasses) {
Set<EClass> result = new LinkedHashSet<EClass>();
EClass referenceType = reference.getEReferenceType();
// 'referenceType: EObject' allows all kinds of EObjects
if (referenceType.equals(EcorePackage.eINSTANCE.getEObject())) {
return allEClasses;
}
for (EClass eClass : allEClasses) {
// can eClass be referenced by reference
if (referenceType.equals(eClass)
|| referenceType.isSuperTypeOf(eClass)) {
result.add(eClass);
}
}
return result;
}
/**
* Sets or adds to a reference for an EObject with any generated instance of
* <code>referenceClass</code> using SetCommand/AddCommand. If the reference
* is not required, <code>random</code> decides whether the reference is set
* or how many EObjects are added to it.
*
* @param eObject
* the EObject to set the reference for
* @param referenceClass
* the EClass all referenced EObject shall be instances of
* @param reference
* the reference to set
* @param random
* the Random-object that randomizes EObjects and their amount
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @param allEObjects
* all existing EObjects mapped to their EClass
*
* @see #addPerCommand(EObject, EStructuralFeature, Collection, Set,
* boolean)
* @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean)
* @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean)
*/
public void setReference(EObject eObject, EClass referenceClass,
EReference reference, Random random,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog,
Map<EClass, List<EObject>> allEObjects) {
List<EObject> possibleReferenceObjects = allEObjects
.get(referenceClass);
Collections.shuffle(possibleReferenceObjects, random);
if (!possibleReferenceObjects.isEmpty()) {
int index = 0;
if (reference.isMany()) {
int numberOfReferences = computeFeatureAmount(reference, random);
for (int i = 0; i < numberOfReferences; i++) {
EObject target = possibleReferenceObjects.get(index);
if (reference.getName().equals("eSuperTypes")) {
if (!target.equals(eObject)) {
this.addPerCommand(eObject,
reference,
possibleReferenceObjects.get(index),
exceptionLog, ignoreAndLog);
} /*else
System.err.println(numberOfReferences + " "+ possibleReferenceObjects.size()
+ "do not generate super types for "
+ target + " " + eObject);*/
} else {
this.addPerCommand(eObject, reference,
possibleReferenceObjects.get(index),
exceptionLog, ignoreAndLog);
}
// ensures every EObject is set at most once
if (++index == possibleReferenceObjects.size()) {
break;
}
}
// Change of referencing
// Delete reference.isRequired() in order to set 0..1 references
// } else if (reference.isRequired() || random.nextBoolean()){
} else {// if (random.nextBoolean()) {
this.setPerCommand(eObject, reference,
possibleReferenceObjects.get(index), exceptionLog,
ignoreAndLog);
}
}
}
/**
* Sets all possible attributes of known types to random values using
* {@link IAttributeSetter} and SetCommands/AddCommands.
*
* @param eObject
* the EObject to set attributes for
* @param random
* the Random object used to determine the creation of attributes
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @see IAttributeSetter
* @see AttributeHandler
* @see #addPerCommand(EObject, EStructuralFeature, Collection, Set,
* boolean)
* @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean)
* @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean)
*/
public AttributeHandler attributeHandler = new AttributeHandler();
public void setEObjectAttributes(EObject eObject, Random random,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
Map<EClassifier, IAttributeSetter<?>> attributeSetters = attributeHandler
.getAttributeSetters();
for (EAttribute attribute : eObject.eClass().getEAllAttributes()) {
EClassifier attributeType = attribute.getEAttributeType();
if (!isValid(attribute, eObject, exceptionLog, ignoreAndLog)) {
continue;
}
// the attribute setter used to create new attributes
IAttributeSetter<?> attributeSetter = null;
// is there a setter for this attribute?
if (attributeSetters.containsKey(attributeType)) {
attributeSetter = attributeSetters.get(attributeType);
} else if (isEnum(attributeType)) {
attributeSetter = attributeHandler
.getEEnumSetter((EEnum) attributeType);
}
// was there a fitting attribute setter?
if (attributeSetter != null) {
if (attribute.isMany()) {
int numberOfAttributes = computeFeatureAmount(attribute,
random);
addPerCommand(eObject, attribute,
attributeSetter
.createNewAttributes(numberOfAttributes),
exceptionLog, ignoreAndLog);
} else {
setPerCommand(eObject, attribute,
attributeSetter.createNewAttribute(), exceptionLog,
ignoreAndLog);
}
}
}
}
/**
* Returns whether <code>attributeType</code> is an instance of EEnum.
*
* @param attributeType
* the EClassifier in question
* @return is <code>attributeType</code> an instance of EEnum?
*/
private boolean isEnum(EClassifier attributeType) {
return EcorePackage.eINSTANCE.getEEnum().isInstance(attributeType);
}
/**
* Computes the random amount of objects to add to a feature.
*
* @param feature
* the feature to compute the amount of objects for
* @param random
* the Random object used to obtain random values
* @return 1 if the feature is single valued,<br>
* a random value from 0 to 10 if the feature is many-valued and has
* no upper bound,<br>
* a random value between the feature's lower and upper bound
* otherwise
*/
private int computeFeatureAmount(EStructuralFeature feature,
Random random) {
if (!feature.isMany()) {
return 1;
}
if (feature.getUpperBound() < feature.getLowerBound()) {
return random.nextInt(10);
}
return feature.getLowerBound()
+ random.nextInt(feature.getUpperBound()
- feature.getLowerBound() + 1);
}
/**
* Deletes an EObject, while exceptions are handled with the values
* specified.
*
* @param eObject
* the EObject to delete
* @param exceptionLog
* the current log of exceptions
* @param ignoreAndLog
* should exceptions be ignored and added to
* <code>exceptionLog</code>?
* @see EcoreUtil#delete(EObject)
*/
public void delete(EObject eObject,
Set<RuntimeException> exceptionLog, boolean ignoreAndLog) {
try {
EcoreUtil.delete(eObject, true);
} catch (RuntimeException e) {
handle(e, exceptionLog, ignoreAndLog);
}
}
}